<template>
  <div class="menu-page">
    <ProTable
      ref="proTableRef"
      tableTitle="资源列表"
      :columns="columns"
      :request="fetchFuncTree"
      :defaultIndexColume="false"
      :pagination="false"
      :rowKey="(row) => row.id"
      autoHeight
    >
      <template #operation>
        <n-button type="primary" @click="handleAddFunc">新增菜单</n-button>
      </template>
    </ProTable>

    <n-drawer
      class="menu-drawer"
      v-model:show="drawerActive"
      :defaultWidth="700"
      resizable
      :maskClosable="false"
      @afterLeave="resetModel"
    >
      <n-drawer-content closable>
        <template #header>
          {{ handleTag }}
        </template>

        <n-form
          ref="formRef"
          :model="model"
          :rules="rules"
          labelPlacement="left"
          labelWidth="auto"
        >
          <n-grid cols="24">
            <n-gi span="24">
              <n-form-item label="资源类型" path="funcType">
                <n-radio-group v-model:value="model.funcType">
                  <n-radio :value="1" :disabled="funcTypeDisabled.directory">
                    目录
                  </n-radio>
                  <n-radio
                    :value="2"
                    style="margin: 0px 40px"
                    :disabled="funcTypeDisabled.menu"
                  >
                    菜单
                  </n-radio>
                  <n-radio :value="3" :disabled="funcTypeDisabled.button">
                    按钮
                  </n-radio>
                </n-radio-group>
              </n-form-item>
            </n-gi>

            <n-gi span="12">
              <n-form-item label="资源名称" path="funcName">
                <n-input
                  v-model:value="model.funcName"
                  placeholder="请输入资源名称"
                />
              </n-form-item>
            </n-gi>

            <n-gi span="12">
              <n-form-item label="上级资源" path="parentId">
                <NTreeSelect
                  v-model:value="model.parentId"
                  placeholder="请选择"
                  :options="treeSelectOptons"
                  keyField="id"
                  labelField="funcName"
                />
              </n-form-item>
            </n-gi>

            <n-gi span="12" v-if="model.funcType !== FuncTypeEnum.button">
              <n-form-item label="图标" path="funcIcon">
                <pro-icon-select v-model:value="model.funcIcon">
                  <n-input-group>
                    <n-input
                      v-model:value="model.funcIcon"
                      placeholder="请选择图标"
                      readonly
                    />
                    <n-input-group-label>
                      <div
                        style="height: 100%; display: flex; align-items: center"
                      >
                        <icons
                          :name="model.funcIcon || 'i-application-menu'"
                          size="20"
                        />
                      </div>
                    </n-input-group-label>
                  </n-input-group>
                </pro-icon-select>
              </n-form-item>
            </n-gi>

            <n-gi span="12">
              <n-form-item label="排序" path="sortOrder">
                <n-input-number
                  v-model:value="model.sortOrder"
                  style="width: 100%"
                />
              </n-form-item>
            </n-gi>

            <n-gi span="12" v-if="model.funcType !== FuncTypeEnum.button">
              <n-form-item label="路由地址" path="url">
                <n-input
                  v-model:value="model.url"
                  placeholder="请输入路由地址"
                />
              </n-form-item>
            </n-gi>

            <n-gi span="12" v-if="model.funcType === FuncTypeEnum.menu">
              <n-form-item label="路由参数" path="routeQuery">
                <n-input
                  v-model:value="model.value.routeQuery"
                  placeholder="输入路由参数"
                />
              </n-form-item>
            </n-gi>

            <n-gi span="12" v-if="model.funcType === FuncTypeEnum.menu">
              <n-form-item label="组件路径" path="compPath">
                <n-input
                  v-model:value="model.compPath"
                  placeholder="请输入组件路径"
                />
              </n-form-item>
            </n-gi>

            <n-gi span="12" v-if="model.funcType === FuncTypeEnum.menu">
              <n-form-item label="组件名称" path="compName">
                <n-input
                  v-model:value="model.compName"
                  placeholder="请输入组件名称"
                />
              </n-form-item>
            </n-gi>

            <!-- <n-gi span="12">
              <n-form-item label="权限标识" path="funcPerms">
                <n-input
                  v-model:value="model.funcPerms"
                  placeholder="请输入权限标识"
                />
              </n-form-item>
            </n-gi> -->

            <template v-if="model.funcType !== FuncTypeEnum.button">
              <n-gi span="12" v-if="model.funcType !== FuncTypeEnum.button">
                <n-form-item label="是否显示">
                  <pro-switch-button
                    v-model:value="model.isDisplay"
                    :checkedValue="1"
                    :uncheckedValue="0"
                    checkedText="是"
                    uncheckedText="否"
                  />
                </n-form-item>
              </n-gi>

              <n-gi span="12" v-if="model.funcType === FuncTypeEnum.menu">
                <n-form-item label="是否缓存">
                  <pro-switch-button
                    v-model:value="model.isCache"
                    :checkedValue="1"
                    :uncheckedValue="0"
                    checkedText="是"
                    uncheckedText="否"
                  />
                </n-form-item>
              </n-gi>
            </template>
            <n-form-item label="备注">
              <n-input type="textarea" v-model:value="model.remark" />
            </n-form-item>
          </n-grid>
        </n-form>

        <template #footer>
          <n-button style="margin-right: 10px" @click="drawerActive = false">
            取消
          </n-button>
          <n-button
            type="primary"
            :loading="confirmLoading"
            @click="handleConfirm()"
          >
            确认
          </n-button>
        </template>
      </n-drawer-content>
    </n-drawer>
  </div>
</template>

<script setup lang="ts">
  import { FormInst } from 'naive-ui'
  import { cloneDeep } from 'lodash-es'
  import { treeForEach } from '@/utils/tree'
  import { FuncTypeEnum } from './enum'
  import { useFuncApi } from './hooks/useFuncApi'
  import { useFuncProTable } from './hooks/useFuncProTable'

  const proTableRef = ref<any>(null)

  const funcTree = ref([])
  const drawerActive = ref(false)
  const formRef = ref<FormInst | null>()
  const handleType = ref<'add' | 'edit' | ''>('')
  const handleTag = computed(() =>
    handleType.value === 'add' ? '新增资源' : '修改资源'
  )
  const [model, resetModel] = useProRef<any>({
    funcType: 1,
    validFlag: true,
    isDisplay: true,
    isCache: false
  })

  const rules: any = {
    funcName: {
      required: true,
      trigger: ['blur'],
      message: '资源名称不能为空'
    },
    parentId: {
      type: 'number',
      required: true,
      trigger: ['blur', 'change'],
      message: '上级资源不能为空'
    },
    sortOrder: {
      type: 'number',
      required: true,
      trigger: ['blur', 'change'],
      message: '排序不能为空'
    },
    url: {
      required: true,
      trigger: ['blur'],
      message: '路由地址不能为空'
    },
    compPath: {
      required: true,
      trigger: ['blur'],
      message: '组件路径不能为空'
    },
    compName: {
      required: true,
      trigger: ['blur'],
      message: '组件名称不能为空'
    }
    // funcPerms: {
    //   required: true,
    //   trigger: ['blur'],
    //   message: '权限标识不能为空'
    // }
  }

  const treeSelectOptons = computed(() => {
    const data: any[] = cloneDeep(funcTree.value)
    const funcType = model.value.funcType
    if (funcType === FuncTypeEnum.directory || funcType === FuncTypeEnum.menu) {
      treeForEach(data, (item) => {
        if (item.children?.[0]?.funcType === FuncTypeEnum.menu) {
          item.children = null
        }
      })
      data.unshift({
        id: 0,
        funcName: '根目录'
      })
    } else if (model.value.funcType === FuncTypeEnum.button) {
      treeForEach(data, (item) => {
        if (item.children?.[0]?.funcType === FuncTypeEnum.button) {
          item.children = null
        }

        if (item.funcType === FuncTypeEnum.directory) {
          item.disabled = true
        }
      })
    }
    return data
  })

  const funcTypeDisabled = computed(() => {
    const status = {
      directory: false,
      menu: false,
      button: false
    }

    if (handleType.value === 'add' && model.value.parentId) {
      const funcType = model.value.oldFuncType
      if (funcType === FuncTypeEnum.directory) {
        status.button = true
      }
      if (funcType === FuncTypeEnum.menu) {
        status.directory = true
        status.menu = true
      }
    } else if (handleType.value === 'edit') {
      status.button = true
      status.menu = true
      status.directory = true
    }
    return status
  })

  const handleAddFunc = () => {
    drawerActive.value = true
    handleType.value = 'add'
  }

  const handleAddChildFunc = (row) => {
    resetModel()
    model.value.oldFuncType = row.funcType
    model.value.funcType = (row.funcType as number) + 1 || 1
    model.value.parentId = row.id
    drawerActive.value = true
    handleType.value = 'add'
  }

  const handleEditFunc = (row) => {
    model.value = { ...row }
    drawerActive.value = true
    handleType.value = 'edit'
  }

  const handleDelFunc = (id) => {
    fetchDelFunc(id, () => {
      proTableRef.value.reload()
    })
  }

  const handleConfirm = () => {
    formRef.value?.validate((errors) => {
      if (errors) return
      fetchAddOrEditFunc(() => {
        drawerActive.value = false
        proTableRef.value.reload()
        drawerActive.value = false
      })
    })
  }

  const { fetchFuncTree, fetchAddOrEditFunc, fetchDelFunc, confirmLoading } =
    useFuncApi({
      handleType,
      handleTag,
      funcTree,
      model
    })

  const { columns } = useFuncProTable({
    handleAddChildFunc,
    handleDelFunc,
    handleEditFunc
  })
</script>

<style lang="less">
  .menu-drawer {
    .n-form-item {
      margin: 0px 15px;
    }

    .n-tree-node-content {
      color: #2d2f32 !important;
    }
  }

  .menu-page {
    .n-data-table-thead {
      .func-name {
        text-align: center !important;
      }
    }

    .n-data-table-tbody {
      .func-name {
        padding-left: 20px;
      }
    }
  }
</style>
